package com.totoro.rpc.service;

import com.totoro.rpc.common.bean.RPCRequest;
import com.totoro.rpc.common.bean.RPCResponse;
import com.totoro.rpc.common.codec.RPCDecoder;
import com.totoro.rpc.common.codec.RPCEncoder;
import com.totoro.rpc.common.util.NetworkUtil;
import com.totoro.rpc.register.Register;
import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.ChannelPipeline;
import io.netty.channel.EventLoopGroup;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import lombok.AccessLevel;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;

import java.util.HashMap;
import java.util.Map;

/**
 * RPC服务，用来对外提供服务
 * Created by Niki on 2018/5/21 18:40
 */
@Slf4j
@AllArgsConstructor(access = AccessLevel.PUBLIC)
public class RPCServer {
    /* 服务对应的长名称以及Class对象的字典 */
    private static Map<String, Class<?>> handlerMap = new HashMap<String, Class<?>>();

    /* 暴露服务的端口 */
    private int port ;

    private Register register;

    /**
     * 启动server服务监听请求
     * 系统启动时该类必须被调用
     */
    public void startServer() {
        EventLoopGroup bossGroup = new NioEventLoopGroup();
        EventLoopGroup workerGroup = new NioEventLoopGroup();

        ServerBootstrap bootstrap = new ServerBootstrap();
        bootstrap.group(bossGroup, workerGroup);

        bootstrap.childHandler(new ChannelInitializer<SocketChannel>() {
            protected void initChannel(SocketChannel socketChannel) throws Exception {
                ChannelPipeline pipeline = socketChannel.pipeline();
                pipeline.addLast(new RPCDecoder(RPCRequest.class));
                pipeline.addLast(new RPCEncoder(RPCResponse.class));
                pipeline.addLast(new RPCServiceHandler(handlerMap));
            }
        });
        registServer();
        try {
            //启动 RPC 服务
            ChannelFuture future = bootstrap.bind(port).sync();
            future.channel().closeFuture().sync();
        } catch (InterruptedException e) {
            log.error("服务启动失败！", e);
        }finally {
            workerGroup.shutdownGracefully();
            bossGroup.shutdownGracefully();
        }
    }

    /**
     * 注册服务
     */
    private void registServer() {
        if (handlerMap == null || handlerMap.isEmpty()) {
            log.info("没有需要注册的服务！");
            return;
        }

        for (Map.Entry<String, Class<?>> entry : handlerMap.entrySet()) {
            register.registerService(entry.getKey(), NetworkUtil.getLocalAddress(port));
        }
    }

}
